﻿#if !Profile && CPPMEM_V1
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using O1.Kernel;
using O1.Kernel.Storage;
using O1.Kernel.Storage.Transactions;

namespace O1.Profiling
{
    class Program
    {
#if !DEBUG
        private const int size = 1024 * 1024;// * 10;
#endif
#if DEBUG
        private const int size = 1;
#endif

        // effect of padding? will spill to the next 16 byte boundary once 8 bytes are exceeded, requires 8 bytes of memory overhead for malloc

        private const int MaxCellSz = 4096;

        static void Main(string[] args)
        {
            var proc = Process.GetCurrentProcess();
            var bytesAllocated = proc.WorkingSet64;

            Console.Write("Before allocation...");
            Console.ReadLine();

            var stopwatch = Stopwatch.StartNew();
            var trunk = new O1.Storage.SingleVersionStore(size);

            Console.WriteLine("Size of edge with padding " + O1.Storage.Instruments.SizeOfEdge() + ".");

            Console.WriteLine("Allocated " + size + " trunk storage.");
            Console.WriteLine("...in " + stopwatch.ElapsedMilliseconds + " milliseconds.");

            Console.Write("Before cell population...");
            Console.ReadLine();

            stopwatch.Restart();
            for(int i = 0; i < size; i++)
            {
                //var index = trunk.Add(new byte[Math.Max(i % MaxCellSz, 16)]);
                var index = trunk.Add(new byte[MaxCellSz]);
                //var buffer = BufferExtensions.GetFreeBuffer(MaxCellSz);
                //var index = trunk.Add(buffer);
                //buffer.ReleaseToPool();
            }

            for (int i = 0; i < size; i++)
            {
                var data = trunk.Read(i);
                data[0] = 255;
                trunk.Write(i, data);

                //data = trunk.Read(i, 2, 2);
                //data[1] = 255;
                //trunk.Write(i, data, 3);
                //trunk.Commit(i, 3);
#if !DEBUG
                //data = trunk.Read(i, 3, 3);
#endif
#if DEBUG
                data = trunk.Read(i, 3, 1);
                data[2] = 255;
                trunk.Write(i, data, 4);
                trunk.Commit(i, 4);

                data = trunk.Read(i, 1, 1);
                data = trunk.Read(i, 2, 1);
                data = trunk.Read(i, 3, 1);
                data = trunk.Read(i, 4, 1);

                data = trunk.Read(i, 1, 1);
                data = trunk.Read(i, 2, 2);
                data = trunk.Read(i, 3, 3);
                data = trunk.Read(i, 4, 4);

                // Nonsense test, expecting GC to return null...
                data = trunk.Read(i, 1, 4);
#endif
            }

            Console.Write("Allocated, Read and updated " + size + " cells ");
            Console.WriteLine("...in " + stopwatch.ElapsedMilliseconds + " milliseconds.");
            Console.ReadLine();

            trunk.Dispose();
            Console.WriteLine("Dispose invoked.");
            Console.ReadLine();
        }
    }
}

#endif